;; EX-37 - Simple Monophonic Midi Contoller

;; This is an instrument posted by JMcC to sc-users.  It is modified
;; to read the frequency, rate and trigger values from control bus
;; inputs.  The post was later comitted as the Stepper UGen help file.

(let* ((rate (In.kr 22))
       (env (Decay2.kr (In.kr 21) 0.002 2.5))
       (freq (In.kr 23))
       (ffreq (Add (Lag2.kr freq) (list 0 0.3))))
  (seq (out (Mix (LFPulse.ar (Mul freq '(1 3/2 2)) 0 0.3)))
       (RLPF.ar out ffreq 0.3 env)
       (RLPF.ar out ffreq 0.3 env)
       (Mul out 0.02)
       (CombL.ar out 1 (FDiv 0.66 rate) 2 0.8 out)
       (let ((rev out))
	 (do-times 5 
		   (set! rev (AllpassN.ar rev 
					  0.05 
					  (random-list 2 0.05) 
					  (random 1.5 2.0))))
	 (Add out (Mul rev 0.3)))
       (LeakDC.ar out)
       (DelayL.ar out 0.1 (SinOsc.kr 0.2 (list 0 half-pi 0.0024 0.0025)) 1 out)
       (OnePole.ar out 0.9)))

;; Map note on events to set the frequency bus value and momentarily
;; place a value on the trigger buss.

(midi-receiver-register 
 (vector #x90 #x9F)
 (lambda (status note velocity) 
   (if (> velocity 0)
       (begin (=>* 0.05 
		  (list "/c_set" 23 (midi-note->frequency note))
		  (list "/c_set" 21 0.05))
	      (=>* (+ 0.05 (* velocity 0.00025)) (list "/c_set" 21 0))))))

;; Map controller one events to set the rate bus value.

(midi-receiver-register
 (vector #xB0 #xBF)
 (lambda (status controller value) 
   (if (= controller 1) 
       (-> "/c_set" 22 (+ 1 (/ value (/ 127 2)))))))

;; Poke the receivers, if no midi setup is enabled.  Use C-cC-q to
;; stop the thread.

(in-mthread
 (-> "/c_set" 22 1.693)
 (let loop ((n 0))
   (midi-receiver-dispatch 
    (list #x90 
	  (ref '(43 55 72 70 55 58 41 67 41 60 55 39 58 55 43 51) n)
	  (randomI 72 96)))
   (thread-sleep! 0.6)
   (loop (modulo (+ n 1) 16))))

;; Clear all midi receivers.

(midi-receiver-clear)
